﻿
using ChongJu.EventManager;
using ChongJu.EventManager.Rating;
using ChongJu.GlobalInfo;
using ChongJu.ImageAnalyze.XCDNN;
using ChongJu.ModelManager.DeviceInfo;
using ChongJu.ModelManager.Rating;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using Public.Logger;
using Public.Tools;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using ChongJu.CloudService;
using System.Xml.Linq;
using System.Security.Policy;

namespace ChongJu.ImageAnalyze
{
    public class AnalyzeService
    {
        private static readonly object _obj = new object();
        private static AnalyzeService _instance;
        public static AnalyzeService Instance
        {
            get
            {
                if (_instance == null)
                    lock (_obj)
                        if (_instance == null)
                            _instance = new AnalyzeService();

                return _instance;
            }
        }

        private List<DictAnalyze> _lst;

        /// <summary>
        /// 状态 初始化
        /// </summary>
        public bool IsInit = false;

        /// <summary>
        /// 是否新模型在创建中
        /// </summary>
        private bool _isCreating = false;

        private Timer _timer;

        private CloudService.CloudService _cloud;


        public AnalyzeService()
        {
            _lst = new List<DictAnalyze>();
            _cloud = new CloudService.CloudService();

            _timer = new Timer(1000 * 3);
            _timer.Elapsed += _timer_Elapsed;
        }

        public bool InitModel(DeviceSiteModel site, bool isInit = false, string modNum = null, string modName = null)
        {
            IsInit = true;
            try
            {
                //下载模型
                var bol = _cloud.Login();
                if (bol == false)
                    return LoadLoaclModel();

                //下载modData文件
                var modJson = _cloud.DownloadMod(modNum ?? site.ModNum);
                var modFile = Path.Combine(ConfigFileInfo.ModelConfigDir, "modData.json");
                bol = Tool.Wirte(modFile, modJson);
                if (bol == false)
                    return false;

                //下载Auto文件
                if (DownloadAutoZip(site) != null)
                {
                    CommonEvent.OnRunLogger("下载Auto件异常");
                    return false;
                }

                //后台自动下载深度学习文件，下次启动时减压更新
                var name = site.ModTargetVersion;
                var msg = DownloadBigDll(name);

                //加载模型
                return ReloadModel(modName ?? site.ModName);
            }
            catch (Exception ex)
            {
                Logger.Error("下载模型异常：", ex);
                _cloud.UploadLog("下载模型异常：" + ex.Message, GlobalVar.DeviceID);
                IsInit = false;
                return false;
            }
            finally
            {
                IsInit = false;
            }
        }

        public RatingResultModel TaskAnalyze(Bitmap image, BitmapData imgData, float weight, string imgPath = null, bool isUp = true)
        {
            var find = _lst.Find(q => q.IsUse == false & q.IsLoading == false);
            if (find == null)
            {
                Logger.Error("图片解析对象繁忙！！！");
                return null;
            }

            find.IsUse = true;
            RatingResultModel result = null;
            try
            {
                result = find.Analyze.TaskAnalyze(image, imgData, weight, isUp);
                if (result != null)
                    result.AnalyzeID = find.ID;
            }
            catch (Exception ex)
            {
                Logger.Error("调用执行分拣dll异常：", ex);
            }
            finally
            {
                find.IsUse = false;
            }

            if (result == null & isUp == true)
                Logger.Error("解析图片结果为NULL-001");

            return result;
        }

        public string GetModelVersoin()
        {
            if (_lst == null || _lst.Count == 0)
                return null;

            return _lst[0].Analyze.GetModelVersoin();
        }

        public string SaveSegmentImage(int id, string dirPath, string levelCode, double weight)
        {
            var find = _lst.Find(q => q.ID == id);
            if (find == null)
                return null;

            return find.Analyze.SaveSegmentImage(dirPath, levelCode, weight);
        }

        public Bitmap GetSegmentImage(int id, PixelFormat pixelFormat)
        {
            var find = _lst.Find(q => q.ID == id);
            if (find == null)
                return null;

            return find.Analyze.GetSegmentImage(pixelFormat);
        }

        public void AnalyzeEnd(int id)
        {
            var find = _lst.Find(q => q.ID == id);
            if (find != null)
                find.IsUse = false;
        }

        public bool LoadLoaclModel()
        {
            try
            {
                var modFile = Path.Combine(ConfigFileInfo.ModelConfigDir, $"modData.json");
                if (File.Exists(modFile) == false)
                {
                    Logger.Error($"模型文件不存在");
                    return false;
                }

                var content = Tool.Read(modFile);
                JObject json = (JObject)JsonConvert.DeserializeObject(content);
                if (json["modName"] == null)
                    return false;

                return ReloadModel(json["modName"].ToString());
            }
            catch (Exception ex)
            {
                Logger.Error($"云端登录失败\r\n加载本地模型异常", ex);
                return false;
            }
        }

        private bool ReloadModel(string modName)
        {
            try
            {
                if (_isCreating == true)
                    return false;

                _isCreating = true;
                if (_lst.Count == 0)  //初始化时加载两个对象  改为只要一个对象
                    for (int i = 0; i < 1; i++)
                    {
                        //必须等模型加载完才能改IsMain为true；，创建的时候必须是fasle
                        var an = new DictAnalyze() { Analyze = new TbcoRatingAnalyze(), IsUse = false, ID = i, IsAginLoad = false };
                        var bol = an.Analyze.LoadLocalModel();
                        //var nm = an.Analyze.GetModelVersoin();
                        if (bol == false)
                        {
                            Logger.Error($"加载本地模型失败 ID:{an.ID}");
                            return false;
                        }
                        else
                            _lst.Add(an);

                        ConnectStatusEvent.OnConnect(ConnectType.ModelDll, bol);
                    }
                else
                {
                    _lst.ForEach(q => q.IsAginLoad = true);
                    _timer.Start();
                }

                //模型模型处理显示
                try
                {
                    if (string.IsNullOrWhiteSpace(modName) == false)
                    {
                        Logger.Info($"加载模型：{modName}");
                        CommonEvent.OnWeightLogger(modName);
                    }
                }
                catch (Exception ex)
                {
                    CommonEvent.OnWeightLogger(modName);
                    Logger.Error($"解析模型名称异常 {modName}", ex);
                }

                return true;
            }
            catch (Exception ex)
            {
                Logger.Error($"重新加载模型异常", ex);
                _cloud.UploadLog("加载模型异常：" + ex.Message, GlobalVar.DeviceID);
                return false;
            }
            finally
            {
                _isCreating = false;
            }
        }


        public void IsDllLogger(bool bol)
        {
            _lst.ForEach(q => q.Analyze.IsDllLogger(bol));
        }

        private void _timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            if (_lst.Exists(q => q.IsAginLoad == true) == false)
                _timer.Stop();
            else
            {
                foreach (var item in _lst)
                {
                    if (item.IsLoading == true | item.IsUse == true)
                        continue;

                    item.IsLoading = true;
                    var bol = item.Analyze.LoadLocalModel(true);
                    if (bol == true)
                        item.IsAginLoad = false;
                    item.IsLoading = false;

                    ConnectStatusEvent.OnConnect(ConnectType.ModelDll, bol);
                }
            }
        }

        private string DownloadAutoZip(DeviceSiteModel site)
        {
            try
            {
                if(site.AutoID == 0)
                {
                    CommonEvent.OnRunLogger("不下载模型Auto文件");
                    return null;
                }

                //下载zip
                var bytes = _cloud.DownloadModZip(site.AutoID);
                if (bytes == null)
                {
                    _cloud.UploadLog("下载Auto Zip文件异常, 为null", GlobalVar.DeviceID);
                    return "下载Auto文件异常, 为null";
                }

                if (Directory.Exists(ConfigFileInfo.ModelDownloadDir) == false)
                    Directory.CreateDirectory(ConfigFileInfo.ModelDownloadDir);
                var zipOri = Path.Combine(ConfigFileInfo.ModelDownloadDir, "cfgZip.zip");
                if (File.Exists(zipOri) == true)
                    File.Delete(zipOri);
                Tool.BytesToFile(zipOri, bytes);
                //减压文件
                if (Directory.Exists(ConfigFileInfo.ModZipCfg) == true)
                    Directory.Delete(ConfigFileInfo.ModZipCfg, true);
                Directory.CreateDirectory(ConfigFileInfo.ModZipCfg);
                ZipFile.ExtractToDirectory(zipOri, ConfigFileInfo.ModZipCfg);
                File.Delete(zipOri);

                GlobalVar.GlobalParamer.AutoID = site.AutoID;
                GlobalVar.UpdateGlobalParamer(GlobalVar.GlobalParamer);
                return null;
            }
            catch (Exception ex)
            {
                _cloud.UploadLog("下载Auto文件异常:" + ex.Message, GlobalVar.DeviceID);
                return ex.Message;
            }
        }

        private string DownloadBigDll(string fileName)
        {
            if (string.IsNullOrWhiteSpace(fileName) || fileName == GlobalVar.GlobalParamer.DllFileName)
                return null;

            var temp = fileName.Split('_');
            var bol = long.TryParse(temp[0], out var fileSize);
            var file = Path.Combine(ConfigFileInfo.ZipModelDownloadDir, $"{fileName}.zip");

            if(bol == true & fileSize <= 1024 * 1024 * 3) //小于3M的文件直接下载，再初始化模型
                _cloud.DownloadDll(fileName, file);

            if (File.Exists(file) == true)
            {
                var size = fileName.Split('_');
                if (size.Length == 3)
                {
                    FileInfo fileInfo = new FileInfo(file);
                    var p = long.TryParse(size[2], out var tmp);
                    if (p == true & tmp == fileInfo.Length)
                    {
                        //减压文件
                        var zipDir = Path.Combine(ConfigFileInfo.ZipModelDownloadDir, fileName);
                        if (Directory.Exists(zipDir) == true)
                            Directory.Delete(zipDir, true);

                        ZipFile.ExtractToDirectory(file, zipDir);
                        Tool.DirToDir(zipDir, ConfigFileInfo.DLModelDir);
                        Directory.Delete(zipDir, true); //删除减压后的文件夹

                        GlobalVar.GlobalParamer.DllFileName = fileName;
                        GlobalVar.UpdateGlobalParamer(GlobalVar.GlobalParamer);
                        File.Delete(file); //删除压缩包
                    }
                }
            }
            else
            {
                Task.Run(() => _cloud.DownloadDll(fileName, file));
            }

            return null;
        }

        public void CalibraLightCamera(IntPtr imgDir,
            int targetb, int targetg, int targetr,
            ref double gradb, ref double gradg, ref double gradr,
            ref int stepL,
            ref int stepb, ref int stepg, ref int stepr, ref int sucesFlag)
        {
            _lst.FirstOrDefault()?.Analyze.CalibraLightCamera(imgDir,
                targetb, targetg, targetr,
                ref gradb, ref gradg, ref gradr,
                ref stepL,
                ref stepb, ref stepg, ref stepr, ref sucesFlag);
        }

        public DictAnalyze GetFrist()
        {
            return _lst.FirstOrDefault();
        }
    }

    public class DictAnalyze
    {
        /// <summary>
        /// 解析对象
        /// </summary>
        public IAnalyzeBase Analyze { get; set; }

        /// <summary>
        /// 是否在解析中
        /// </summary>
        public bool IsUse { get; set; }

        /// <summary>
        /// 解析ID
        /// </summary>
        public int ID { get; set; }

        ///// <summary>
        ///// 是否是主解析
        ///// </summary>
        //public bool IsMain { get; set; }

        /// <summary>
        /// 是否需要重新加载模型标志
        /// </summary>
        public bool IsAginLoad { get; set; }

        /// <summary>
        /// 加载模型中
        /// </summary>
        public bool IsLoading { get; set; }
    }
}
